package com.fjwt.gz.task.activity;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fjwt.gz.db.entity.AgentInfoEntity;
import com.fjwt.gz.db.entity.StatActe017RecordEntity;
import com.fjwt.gz.service.impl.AgentInfoService;
import com.fjwt.gz.service.impl.FansAwardService;
import com.fjwt.gz.service.impl.ScoreRecordTotalService;
import com.fjwt.gz.service.mapper.StatActe017RecordMapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * ACTE017越减越便宜活动--用户参与记录明细
 */
@Component
@Slf4j
public class ACTE017RecordTask {

    @Autowired
    private FansAwardService fansAwardService;
    @Autowired
    private ScoreRecordTotalService scoreRecordTotalService;
    @Autowired
    private AgentInfoService agentInfoService;
    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    private static final int QUERY_PAGE_SIZE = 10000; //每次查询数量

    private static final int SAVE_BATCH_SIZE = 2000; //每次查询数量

//    @Scheduled(cron = "0 20 * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void fansRecord() {
        log.info("开始进入：ACTE017越减越便宜活动--用户参与记录明细 的定时任务，开始时间:{}", DateUtil.now());
        int currentPageIndex = 1; // 当前页数
        while (true) {
            try {
                IPage<StatActe017RecordEntity> recordEntityListPage =
                        fansAwardService.getStatActe017Record(new Page(currentPageIndex, QUERY_PAGE_SIZE));
                log.info("查询页数：{}，size:{}，结果list：{}", currentPageIndex, QUERY_PAGE_SIZE, JSONUtil.toJsonStr(recordEntityListPage));

                // 本次查询结果为空 跳出当前循环
                if (ObjectUtil.isEmpty(recordEntityListPage.getRecords())) {
                    break;
                }

                // 对B2 福分奖品的对应字段赋值
                setB2GetNum(recordEntityListPage.getRecords());

                // 对 入链渠道机构ID 1 - 4 进行赋值
                setAgentInfoIds(recordEntityListPage.getRecords());

                // 对 入链渠道机构name 1 - 4 进行赋值
                setAgentInfoNames(recordEntityListPage.getRecords());

                // 批量新增
                addBatch(recordEntityListPage.getRecords());

                currentPageIndex++;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        log.info("结束：ACTE017越减越便宜活动--用户参与记录明细 的定时任务，结束时间:{}", DateUtil.now());
    }

    /**
     * 批量新增
     * @param record
     */
    private void addBatch(List<StatActe017RecordEntity> record){
        // 使用原生 批处理的形式进行插入
        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
            // 分批插入数据
            List<List<StatActe017RecordEntity>> partition =
                    Lists.partition(record, SAVE_BATCH_SIZE);

            StatActe017RecordMapper statActe017RecordMapper = sqlSession.getMapper(StatActe017RecordMapper.class);
            partition.parallelStream()
                    .forEach(statActe017RecordMapper::insert);
            sqlSession.commit();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 对B2积分奖品获取的数量进行赋值
     *
     * @param recordEntityList
     */
    private void setB2GetNum(List<StatActe017RecordEntity> recordEntityList) {
        // 对查询到的数据进行处理
        Map<String, StatActe017RecordEntity> afgTmpMap =
                recordEntityList.parallelStream()
                        .collect(Collectors.toMap(
                                item -> item.getActivityId() + "_" + item.getFansId() + "_" + item.getLiteAppId(), Function.identity())
                        );

        // 获取活动ID集合
        List<Long> acteIdList =
                recordEntityList.parallelStream()
                        .map(StatActe017RecordEntity::getActivityId).distinct().toList();
        // 获取用户ID集合
        List<Long> fansIdList =
                recordEntityList.parallelStream()
                        .map(StatActe017RecordEntity::getFansId).distinct().toList();
        // 获取AppID集合
        List<String> appIdList =
                recordEntityList.parallelStream()
                        .map(StatActe017RecordEntity::getLiteAppId).distinct().toList();

        log.info("acteIdList:{}, fansIdList:{}, appIdList:{}", acteIdList, fansIdList, appIdList);

        List<Map<String, Object>> scoreSumList = this.scoreRecordTotalService.getScoreCount(acteIdList, fansIdList, appIdList);

        log.info("scoreSumList :{}", scoreSumList);
        // 遍历 对 B2 赋值
        scoreSumList.forEach(item -> {
            StatActe017RecordEntity val = afgTmpMap.get(item.get("ws_keys"));
            if (!ObjectUtil.isEmpty(val)) {
                val.setB2GetNum(Integer.parseInt((String) item.get("score_count")));
            }
        });
    }

    /**
     * 对入链渠道机构ID 1-4
     *
     * @param recordEntityList
     */
    private void setAgentInfoIds(List<StatActe017RecordEntity> recordEntityList) {
        // 获取所有的入链渠道的网点号
        Map<String, List<StatActe017RecordEntity>> agentNoTmpMap =
                recordEntityList.parallelStream()
                        .filter(item -> ObjectUtil.isNotEmpty(item.getFirstChannelCode()))
                        .collect(Collectors.groupingBy(
                                item -> item.getFirstChannelCode().split("-")[0])
                        );
        if (ObjectUtil.isEmpty(agentNoTmpMap)) {
            return;
        }
        log.info("入链渠道网点号 agentNoTmpMap：{}", agentNoTmpMap);
        // 获取所有网点号的信息
        Map<String, AgentInfoEntity> agentInfoEntityMap =
                this.agentInfoService.getAgentInfos(agentNoTmpMap.keySet().stream().toList()).parallelStream()
                        .filter(item -> ObjectUtil.isNotEmpty(item.getAgentNo()))
                        .collect(Collectors.toMap(AgentInfoEntity::getAgentNo, Function.identity()));

        // 对agentNoId 1 - 4 进行赋值
        agentNoTmpMap.forEach((k, v) -> {
            AgentInfoEntity agentInfo = agentInfoEntityMap.get(k);
            v.parallelStream().forEach(item -> {
                item.setChannelAgentNo1(agentInfo.getAgentNo1().equals("0") ? null : agentInfo.getAgentNo1());
                item.setChannelAgentNo2(agentInfo.getAgentNo2().equals("0") ? null : agentInfo.getAgentNo2());
                item.setChannelAgentNo3(agentInfo.getAgentNo3().equals("0") ? null : agentInfo.getAgentNo3());
                item.setChannelAgentNo4(agentInfo.getAgentNo4().equals("0") ? null : agentInfo.getAgentNo4());
            });
        });
    }

    /**
     * 对入链渠道机构Name 1-4
     *
     * @param recordEntityList
     */
    private void setAgentInfoNames(List<StatActe017RecordEntity> recordEntityList) {

        // 入链渠道 机构ID1
        Map<String, List<StatActe017RecordEntity>> agentNo1ListMap =
                recordEntityList.parallelStream()
                        .filter(item -> ObjectUtil.isNotEmpty(item.getChannelAgentNo1()))
                        .collect(Collectors.groupingBy(StatActe017RecordEntity::getChannelAgentNo1));

        // 入链渠道 机构ID2
        Map<String, List<StatActe017RecordEntity>> agentNo2ListMap =
                recordEntityList.parallelStream()
                        .filter(item -> ObjectUtil.isNotEmpty(item.getChannelAgentNo2()))
                        .collect(Collectors.groupingBy(StatActe017RecordEntity::getChannelAgentNo2));

        // 入链渠道 机构ID3
        Map<String, List<StatActe017RecordEntity>> agentNo3ListMap =
                recordEntityList.parallelStream()
                        .filter(item -> ObjectUtil.isNotEmpty(item.getChannelAgentNo3()))
                        .collect(Collectors.groupingBy(StatActe017RecordEntity::getChannelAgentNo3));

        // 入链渠道 机构ID4
        Map<String, List<StatActe017RecordEntity>> agentNo4ListMap =
                recordEntityList.parallelStream()
                        .filter(item -> ObjectUtil.isNotEmpty(item.getChannelAgentNo4()))
                        .collect(Collectors.groupingBy(StatActe017RecordEntity::getChannelAgentNo4));

        // 入链渠道 机构name
        Map<String, AgentInfoEntity> agentInfoName1 = getAgentInfoNameMap(agentNo1ListMap.keySet().stream().toList());
        Map<String, AgentInfoEntity> agentInfoName2 = getAgentInfoNameMap(agentNo2ListMap.keySet().stream().toList());
        Map<String, AgentInfoEntity> agentInfoName3 = getAgentInfoNameMap(agentNo3ListMap.keySet().stream().toList());
        Map<String, AgentInfoEntity> agentInfoName4 = getAgentInfoNameMap(agentNo4ListMap.keySet().stream().toList());

        // 赋值
        setAgentInfoNamesSub(1, agentNo1ListMap, agentInfoName1);
        setAgentInfoNamesSub(2, agentNo2ListMap, agentInfoName2);
        setAgentInfoNamesSub(3, agentNo3ListMap, agentInfoName3);
        setAgentInfoNamesSub(4, agentNo4ListMap, agentInfoName4);

    }

    /**
     * 获取整理好的机构名称
     *
     * @param list
     * @return
     */
    private Map<String, AgentInfoEntity> getAgentInfoNameMap(List<String> list) {
        if (ObjectUtil.isEmpty(list)) {
            return null;
        }
        return this.agentInfoService.getAgentInfos(list).parallelStream()
                .collect(Collectors.toMap(AgentInfoEntity::getAgentNo, Function.identity()));
    }

    /**
     * 对agentName 真正进行赋值
     *
     * @param agentNoListMap
     * @param agentInfoNameMap
     */
    private void setAgentInfoNamesSub(int flag, Map<String, List<StatActe017RecordEntity>> agentNoListMap, Map<String, AgentInfoEntity> agentInfoNameMap) {
        if (ObjectUtil.isEmpty(agentInfoNameMap)) {
            return;
        }
        // 对agentNoId 1 - 4 进行赋值
        agentNoListMap.forEach((k, v) -> {
            AgentInfoEntity agentInfo = agentInfoNameMap.get(k);
            v.parallelStream().forEach(item -> {
                switch (flag) {
                    case 1:
                        item.setChannelAgentName1(agentInfo.getAgentName());
                    case 2:
                        item.setChannelAgentName2(agentInfo.getAgentName());
                    case 3:
                        item.setChannelAgentName3(agentInfo.getAgentName());
                    case 4:
                        item.setChannelAgentName4(agentInfo.getAgentName());
                }
            });
        });
    }
}
